// Helper macro definitions
#define ABS(x) ((x)<0?(-(x)):(x))
#define DL_LIST_ENTRY_TASKCB_NAME(entry) (LOS_DL_LIST_ENTRY(entry,LosTaskCB,pendList)->taskName)
#define DL_LIST_ENTRY_TASKCB_EDF_PRIORITY(entry) (((const SchedEDF*)&(LOS_DL_LIST_ENTRY(entry,LosTaskCB,pendList)->sp))->priority)
#define DL_LIST_ENTRY_TASKCB_EDF_FINISH_TIME(entry) (((const SchedEDF*)&(LOS_DL_LIST_ENTRY(entry,LosTaskCB,pendList)->sp))->finishTime)

// NEDF Task Get
STATIC INLINE LosTaskCB *NEDFRunqueueTaskGet(EDFRunqueue *rq)
{
    LOS_DL_LIST *root = &rq->root;
    if (LOS_ListEmpty(root)) {
        return NULL;
    }

    LOS_DL_LIST *currentTaskNode = root->pstNext;

    // There are at least 2 EDF tasks
    if(currentTaskNode->pstNext!=root){
        INT64 im=INT64_MAX;
        
        do {
            LOS_DL_LIST* nextTaskNode=currentTaskNode->pstNext;

            const INT64 currentFinishTimeDiff=ABS((INT64)(
                DL_LIST_ENTRY_TASKCB_EDF_FINISH_TIME(currentTaskNode)
                -DL_LIST_ENTRY_TASKCB_EDF_FINISH_TIME(nextTaskNode)));
                
            if (currentFinishTimeDiff<im) {
                im=currentFinishTimeDiff;
            }
            
            currentTaskNode = currentTaskNode->pstNext;
        } while (currentTaskNode->pstNext != root);

        // Rewind currentTaskNode
        currentTaskNode = root->pstNext;

        if(ABS((INT64)(
            DL_LIST_ENTRY_TASKCB_EDF_FINISH_TIME(currentTaskNode)
            -DL_LIST_ENTRY_TASKCB_EDF_FINISH_TIME(currentTaskNode->pstNext)))<=im){

            LOS_DL_LIST* selectedTaskNode= (DL_LIST_ENTRY_TASKCB_EDF_PRIORITY(currentTaskNode)
                <=DL_LIST_ENTRY_TASKCB_EDF_PRIORITY(currentTaskNode->pstNext))
                ?currentTaskNode
                :(currentTaskNode->pstNext);

            PRINTK("Task %s is selected. We face [%s, priority=%hd] or [%s, priority=%hd]\n",
                DL_LIST_ENTRY_TASKCB_NAME(selectedTaskNode),
                DL_LIST_ENTRY_TASKCB_NAME(currentTaskNode),
                DL_LIST_ENTRY_TASKCB_EDF_PRIORITY(currentTaskNode),
                DL_LIST_ENTRY_TASKCB_NAME(currentTaskNode->pstNext),
                DL_LIST_ENTRY_TASKCB_EDF_PRIORITY(currentTaskNode->pstNext));

            return LOS_DL_LIST_ENTRY(selectedTaskNode, LosTaskCB, pendList);
        }
        else{
            return LOS_DL_LIST_ENTRY(currentTaskNode, LosTaskCB, pendList);
        }
    }
    else{
        return LOS_DL_LIST_ENTRY(currentTaskNode, LosTaskCB, pendList);
    }
}